/*
* Copyright (c) 2007 by Kirill Kolodyazhniy.
* See the file "license.terms" for information on usage and redistribution.
*/

#include "timer.h"
#include <algorithm>

namespace Engine
{
	/**********************************************************************************************************/
	Timer::Timer()
	{
		Reset();
	}
	/**********************************************************************************************************/
	void Timer::Reset()
	{
		QueryPerformanceFrequency(&m_frequency);
		QueryPerformanceCounter(&m_startTime);
		m_startTick = GetTickCount();
	}
	/**********************************************************************************************************/
	unsigned long Timer::GetMilliseconds()const
	{
		LARGE_INTEGER curTime;

		QueryPerformanceCounter(&curTime);

		LONGLONG newTime = curTime.QuadPart - m_startTime.QuadPart;

		// scale by 1000 for milliseconds
		unsigned long ticks = static_cast<unsigned long>(1000 * newTime / m_frequency.QuadPart);

		// detect and compensate for performance counter leaps
		// (surprisingly common, see Microsoft KB: Q274323)
		unsigned long check = GetTickCount() - m_startTick;
		signed long msecOff = static_cast<signed long>(ticks - check);
		if (msecOff < -100 || msecOff > 100)
		{
			// We must keep the timer running forward :)
			LONGLONG adjust = (std::min)(msecOff * m_frequency.QuadPart / 1000, newTime - m_lastTime);
			m_startTime.QuadPart += adjust;
			newTime -= adjust;

			// Re-calculate milliseconds
			ticks = static_cast<unsigned long> (1000 * newTime / m_frequency.QuadPart);
		}

		m_lastTime = newTime;

		return ticks;
	}
	/**********************************************************************************************************/
}
